package org.cable.shop.controller;

import com.alibaba.fastjson.JSONObject;
import com.wechat.pay.contrib.apache.httpclient.auth.ScheduledUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.cable.common.enums.ProductOrderPayTypeEnum;
import org.cable.shop.config.WechatPayConfig;
import org.cable.shop.manager.ProductOrderManager;
import org.cable.shop.service.ProductOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 回调接口
 *
 * @author hsj
 * @date 2023/11/22 15:12
 */

@RestController
@RequestMapping("/api/callback/order/v1")
@Slf4j
public class PayCallBackController {

	@Autowired
	private WechatPayConfig wechatPayConfig;

	@Autowired
	private ProductOrderService productOrderService;

	@Autowired
	private ScheduledUpdateCertificatesVerifier verifier;

	/**
	 * 获取报⽂ 验证签名（确保是微信传输过来的） 解密（AES对称解密出原始数据） 处理业务逻辑 响应请求
	 *
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping("wechat")
	public Map<String, String> wechatPayCallBack(HttpServletRequest request,
		HttpServletResponse response) {
		//获取报⽂
		String body = getRequestBody(request);
		//随机串
		String nonceStr = request.getHeader("Wechatpay-Nonce");
		//微信传递过来的签名
		String signature = request.getHeader("Wechatpay-Signature");
		//证书序列号（微信平台）
		String serialNo = request.getHeader("Wechatpay-Serial");
		//时间戳
		String timestamp = request.getHeader("Wechatpay-Timestamp");

		//构造签名串
		//应答时间戳\n
		//应答随机串\n
		//应答报⽂主体\n
		String signStr = Stream.of(timestamp, nonceStr, body).collect(Collectors.joining("\n", "", "\n"));

		Map<String, String> map = new HashMap<>(2);
		try {
			//验证签名是否通过
			boolean result = verifySign(serialNo, signStr, signature);
			if (result) {
				//解密数据
				String plainBody = decryptBody(body);
				log.info("解密后的明文:{}", plainBody);
				//处理业务逻辑
				Map<String, String> paramMap = convertWechatPayMsgToMap(plainBody);
				productOrderService.processOrderCallBackMsg(ProductOrderPayTypeEnum.WECHAT_PAY,paramMap);
				//响应微信
				map.put("code", "SUCCESS");
				map.put("message", "成功");
			}
		} catch (Exception e) {
			log.error("微信支付回调异常");
		}

		return map;
	}

	/**
	 * 转换body为Map
	 *
	 * @param plainBody
	 * @return
	 */
	private Map<String, String> convertWechatPayMsgToMap(String plainBody) {

		Map<String, String> params = new HashMap<>(2);
		JSONObject jsonObject = JSONObject.parseObject(plainBody);

		//商户订单号
		params.put("out_trade_no", jsonObject.getString("out_trade_no"));
		//交易状态
		params.put("trade_status", jsonObject.getString("trade_status"));
		//附加数据
		params.put("account_no", jsonObject.getJSONObject("attach").getString("accountNo"));

		return params;
	}

	/**
	 * 解密body的密文
	 *
	 * @param body
	 * @return
	 */
	private String decryptBody(String body) throws GeneralSecurityException {

		AesUtil aesUtil = new AesUtil(wechatPayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8));

		JSONObject jsonObject = JSONObject.parseObject(body);
		JSONObject resource = jsonObject.getJSONObject("resource");

		String ciphertext = resource.getString("ciphertext");
		String associatedData = resource.getString("associated_data");
		String nonce = resource.getString("nonce");
		return aesUtil.decryptToString(
			associatedData.getBytes(StandardCharsets.UTF_8),
			nonce.getBytes(StandardCharsets.UTF_8),
			ciphertext
		);

	}

	/**
	 * 获取传输报文
	 *
	 * @param request
	 * @return
	 */
	private String getRequestBody(HttpServletRequest request) {
		StringBuffer sb = new StringBuffer();
		try (
			ServletInputStream inputStream =
				request.getInputStream();
			BufferedReader reader = new
				BufferedReader(new InputStreamReader(inputStream));
		) {
			String line;
			while ((line = reader.readLine()) !=
				null) {
				sb.append(line);
			}
		} catch (IOException e) {
			log.error("读取数据流异常:{}", e);
		}
		return sb.toString();
	}

	/**
	 * 验证签名
	 *
	 * @param serialNo  微信平台-证书序列号
	 * @param signStr   自己组装的签名串
	 * @param signature 微信返回的签名
	 * @return
	 */
	private boolean verifySign(String serialNo, String signStr, String signature) {
		return verifier.verify(serialNo, signStr.getBytes(StandardCharsets.UTF_8), signature);
	}

}
